/* -*- c++ -*-
*
* taglist.cpp
*
* Copyright (C) 2005 Petter Stokke <ummo@hellokitty.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "taglist.h"

#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kpopupmenu.h>
#include <kiconloader.h>
#include <kurldrag.h>

// --- TagList ---

TagList::TagList( BookmarkAPI* api, QWidget* parent, const char* name )
        : KListView( parent, name )
        , m_api( api )
{
    addColumn( i18n( "Tag" ) );
    addColumn( i18n( "Count" ) );
    setColumnAlignment( 1, Qt::AlignRight );
    setFullWidth( true );
    setAllColumnsShowFocus( true );
    setDefaultRenameAction( QListView::Reject );
    setAcceptDrops( true );
    setDropVisualizer( false );
    setDropHighlighter( true );
    setSelectionMode( QListView::Extended );

    connect( this, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ),
             this, SLOT( slotContextMenu( KListView*, QListViewItem*, const QPoint& ) ) );
    connect( this, SIGNAL( selectionChanged() ),
             this, SLOT( slotOpenSelectedTags() ) );
    connect( this, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ),
             this, SLOT( slotDropped( QDropEvent* ) ) );
}

TagListItem* TagList::currentTag() const
{
    return dynamic_cast<TagListItem*>( currentItem() );
}

TagListItem* TagList::findTag( const QString& tagName ) const
{
    QListViewItem * i = firstChild();
    for ( ; i; i = i->nextSibling() ) {
        if ( i->text( 0 ) == tagName )
            return dynamic_cast<TagListItem*>( i );
    }
    return 0;
}

void TagList::updateTags( Collection* c )
{
    clear();
    QStringList t = c->tags();
    QStringList::Iterator it;
    for ( it = t.begin(); it != t.end(); ++it )
        ( void ) new TagListItem( this, *it, c->tagCount( *it ) );
}

void TagList::slotTagRenamed( BookmarkAPIJob* job )
{
    RenameTagJob * j = dynamic_cast<RenameTagJob*>( job );
    Q_ASSERT( j );
    TagListItem * tag = findTag( j->oldTag() );
    if ( !tag )
        return ;
    tag->setTagName( j->newTag() );
    sort();
    emit tagRenamed( j->oldTag(), j->newTag() );
}

void TagList::slotContextMenu( KListView*, QListViewItem* i, const QPoint& pt )
{
    TagListItem * tag = dynamic_cast<TagListItem*>( i );
    KIconLoader* icons = KGlobal::iconLoader();
    KPopupMenu* pop = new KPopupMenu( this );
    pop->insertTitle( i18n( "Tag" ) );
    if ( tag ) {
        pop->insertItem( icons->loadIconSet( "fileopen", KIcon::Small ), i18n( "&Open" ), this, SLOT( slotOpenCurrentTag() ) );
        // pop->insertItem( icons->loadIconSet( "fileimport", KIcon::Small ), i18n( "Posts from &All Users" ), this, SLOT( slotOpenCurrentTagGlobal() ) );
        pop->insertSeparator();
        pop->insertItem( icons->loadIconSet( "edit", KIcon::Small ), i18n( "Re&name" ), this, SLOT( slotRenameCurrentTag() ) );
        pop->insertSeparator();
    }
    pop->insertItem( icons->loadIconSet( "reload", KIcon::Small ), i18n( "&Reload" ), this, SIGNAL( pleaseRefresh() ) );
    pop->popup( pt );
}

void TagList::slotOpenSelectedTags()
{
    QStringList t;
    QListViewItemIterator it( this, QListViewItemIterator::Selected );
    for ( ; it.current(); ++it ) {
        TagListItem* tag = dynamic_cast<TagListItem*>( it.current() );
        if ( tag )
            t.append( tag->tagName() );
    }
    emit tagsSelected( t );
}

void TagList::slotOpenCurrentTagGlobal()
{
    TagListItem * tag = currentTag();
    if ( tag )
        emit globalTagSelected( tag->tagName() );
}

void TagList::slotRenameCurrentTag()
{
    TagListItem * tag = currentTag();
    if ( tag )
        tag->startRename( 0 );
}

bool TagList::acceptDrag( QDropEvent* event ) const
{
    KURL::List uri;
    return KURLDrag::decode( event, uri );
}

void TagList::slotDropped( QDropEvent* event )
{
    QString tag;
    TagListItem* item = dynamic_cast<TagListItem*>( itemAt( contentsToViewport( event->pos() ) ) );
    if ( item )
        tag = item->tagName();
    KURL::List uri;
    if ( KURLDrag::decode( event, uri ) ) {
        QValueListConstIterator<KURL> it;
        for ( it = uri.begin(); it != uri.end(); ++it )
            emit urlDropped( ( *it ).url(), tag );
    }
}



// --- TagListItem ---

TagListItem::TagListItem( TagList* parent, const QString& name, int count )
        : KListViewItem( parent )
        , m_tagName( name )
        , m_tagCount( count )
{
    setRenameEnabled( 0, true );
}

const QString& TagListItem::tagName() const
{
    return m_tagName;
}

void TagListItem::setTagName( const QString& name )
{
    m_tagName = name;
    repaint();
}

void TagListItem::setTagCount( int count )
{
    m_tagCount = count;
    repaint();
}

int TagListItem::tagCount() const
{
    return m_tagCount;
}

QString TagListItem::text( int column ) const
{
    switch ( column ) {
    case 0:
        return tagName();
    case 1:
        return KGlobal::locale() ->formatLong( tagCount() );
    default:
        return QString::null;
    }
}

int TagListItem::compare( QListViewItem* i, int col, bool ascending ) const
{
    TagListItem * other = dynamic_cast<TagListItem*>( i );
    if ( col != 1 || !other )
        return KListViewItem::compare( i, col, ascending );
    return tagCount() - other->tagCount();
}

void TagListItem::setText( int column, const QString& text )
{
    KListViewItem::setText( column, text );
    if ( column )
        return ;
    TagList* list = dynamic_cast<TagList*>( listView() );
    if ( !list )
        return ;
    RenameTagJob* j = list->api() ->renameTag( tagName(), text );
    BookmarkAPIJob* job = dynamic_cast<BookmarkAPIJob*>( j );
    Q_ASSERT( job );
    list->connect( job, SIGNAL( success( BookmarkAPIJob* ) ),
                   list, SLOT( slotTagRenamed( BookmarkAPIJob* ) ) );
}

#include "taglist.moc"
